package SGEngine2

import (
	//"fmt"
	"github.com/glfw"
)

/*EventMessage*/
type EventCallFunc func(*EventMessage, int, int)
type EventMessage struct {
	BaseComponent
	node          *Node
	monitorEvents map[int]*Array
	nodestate     int
	UserData      interface{}
}

func (this *EventMessage) GetNode() *Node {
	return this.node
}
func (e *EventMessage) OnAttach(node *Node) {
	e.node = node
}

func (e *EventMessage) OnDetach(node *Node) {
	EventManager.RemoveEvent(e)
}

func (e *EventMessage) RegisterEvent(eventType int, fn EventCallFunc) {
	if e.monitorEvents == nil {
		e.monitorEvents = make(map[int]*Array)
	}
	if e.monitorEvents[eventType] == nil {
		e.monitorEvents[eventType] = new(Array)
	}
	e.monitorEvents[eventType].Add(fn)
	EventManager.AddEvent(e)
}

func (e *EventMessage) RemoveEvent(eventType int, fn EventCallFunc) {
	e.monitorEvents[eventType].Remove(fn)
}

func (e *EventMessage) OnUpdate() {

}

/*EventManager*/
const (
	EVENT_MOUSEDOWN  = 0
	EVENT_MOUSEUP    = 1
	EVENT_WIN_RESIZE = 2
	EVENT_TYPESIZE   = 3
)
const (
	GEVENT_MOUSEDOWN = 0
	GEVENT_MOUSEUP   = 1
	GEVENT_TYPESIZE  = 2
)

type GlobalEventFunc func(int, int, int, int)

const (
	//0000 0000 0000 0001
	EVENT_STATE_INNODE = 1 //鼠标光标在Node中
)

var EventManager _EventManager

type _EventManager struct {
	MonitorEvents []*Array
	globalEvents  []*Array
}

func (this *_EventManager) Init() {
	this.MonitorEvents = make([]*Array, EVENT_TYPESIZE)
	this.globalEvents = make([]*Array, GEVENT_TYPESIZE)
	for i := 0; i < EVENT_TYPESIZE; i++ {
		this.MonitorEvents[i] = new(Array)
	}
}

func init() {
	EventManager.Init()
}

func (this *_EventManager) AddGlobalEvent(eventType int, fn GlobalEventFunc) {
	if this.globalEvents[eventType] == nil {
		this.globalEvents[eventType] = new(Array)
	}
	this.globalEvents[eventType].Add(fn)
}

func (this *_EventManager) RemoveGlobalEvent(eventType int, fn GlobalEventFunc) {
	this.globalEvents[eventType].Remove(fn)
}

func (this *_EventManager) PushGlobalEvent(eventType int, p0, p1, p2, p3 int) {

	if this.globalEvents[eventType] == nil {
		return
	}
	for i := 0; i < this.globalEvents[eventType].Count(); i++ {
		this.globalEvents[eventType].Get(i).(GlobalEventFunc)(p0, p1, p2, p3)
	}

}

func (this *_EventManager) AddEvent(em *EventMessage) {
	isHave := false
	for i, _ := range em.monitorEvents {
		isHave = false
		for i2 := 0; i2 < this.MonitorEvents[i].Count(); i2++ {
			if this.MonitorEvents[i].Get(i2) == em {
				isHave = true
			}
		}
		if isHave {
			continue
		}
		this.MonitorEvents[i].Add(em)
	}

}

func (this *_EventManager) RemoveEvent(em *EventMessage) {
	for k, _ := range em.monitorEvents {
		this.MonitorEvents[k].Remove(em)
	}
}

func (this *_EventManager) PushEvent(eventType int, x, y int) {
	for i := 0; i < EventManager.MonitorEvents[eventType].Count(); i++ {
		emc := EventManager.MonitorEvents[eventType].Get(i).(*EventMessage)
		for i := 0; i < emc.monitorEvents[eventType].Count(); i++ {
			emc.monitorEvents[eventType].Get(i).(EventCallFunc)(emc, x, y)
		}
	}

}

func (this *_EventManager) EventCatch(node *Node, targetNode *Node, x, y int, eventType int) bool {
	isTrigger := this.IsTrigger(node, x, y)
	RB := false
	if isTrigger && node == targetNode {
		this.EventBubble()
		em := node.Get("EventMessage")
		if em != nil {
			emc := em.(*EventMessage)
			for i := 0; i < emc.monitorEvents[eventType].Count(); i++ {
				emc.monitorEvents[eventType].Get(i).(EventCallFunc)(emc, x, y)
			}
		}
		RB = true
		return true
	}
	if isTrigger && node.childNodes != nil {
		for i := 0; i < node.childNodes.Count(); i++ {
			b := this.EventCatch(node.childNodes.Get(i).(*Node), targetNode, x, y, eventType)
			if b == true {
				RB = true
			}
		}
	}
	return RB
}

func (this *_EventManager) EventBubble() {

}

func (this *_EventManager) IsTrigger(node *Node, x, y int) bool {
	//如果没有Bounds直接通过
	if node.Bounds == nil {
		return true
	}
	Pos := node.GetWorldMat().Position()
	Scale := node.GetWorldMat().Scale()
	b := node.Bounds
	MinX := b.Min.X * Scale.X
	MaxX := b.Max.X * Scale.X
	MinY := b.Min.Y * Scale.Y
	MaxY := b.Max.Y * Scale.Y
	if float64(x) > MinX+Pos.X && float64(x) < MaxX+Pos.X && float64(y) > MinY+Pos.Y && float64(y) < MaxY+Pos.Y {
		return true
	}
	return false
}

func OnMouseClick(button, state int) {
	x, y := glfw.MousePos()
	x = x - RootView.Width/2
	y = (y - RootView.Height/2) * -1
	//MouseDown
	if state == 1 {
		EventManager.PushGlobalEvent(GEVENT_MOUSEDOWN, x, y, button, state)
		for i := 0; i < EventManager.MonitorEvents[EVENT_MOUSEDOWN].Count(); i++ {
			em := EventManager.MonitorEvents[EVENT_MOUSEDOWN].Get(i).(*EventMessage)
			EventManager.EventCatch(RootView.ViewScene.RootNode, em.node, x, y, EVENT_MOUSEDOWN)
		}
		//MouseUP
	} else if state == 0 {
		EventManager.PushGlobalEvent(GEVENT_MOUSEUP, x, y, button, state)
		for i := 0; i < EventManager.MonitorEvents[EVENT_MOUSEUP].Count(); i++ {
			em := EventManager.MonitorEvents[EVENT_MOUSEUP].Get(i).(*EventMessage)
			EventManager.EventCatch(RootView.ViewScene.RootNode, em.node, x, y, EVENT_MOUSEUP)
		}
	}
}
